package com.tbit.uqbike.client.service.impl;

import com.tbit.uqbike.center.pojo.MachineStatus;
import com.tbit.uqbike.client.constant.AccountConfigExtConstant;
import com.tbit.uqbike.client.constant.ControlTypeConstant;
import com.tbit.uqbike.client.constant.MachineStateConstant;
import com.tbit.uqbike.client.constant.MapConstant;
import com.tbit.uqbike.client.dao.core.*;
import com.tbit.uqbike.client.dao.log.AppointMentLogDao;
import com.tbit.uqbike.client.dao.ter.TerOnlineDao;
import com.tbit.uqbike.client.exception.BaseException;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.pojo.newEntity.AccountConfigExt;
import com.tbit.uqbike.client.service.*;
import com.tbit.uqbike.client.util.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author: chen
 * @Description: 预约
 * @Date: 创建于 11:51 2020/8/17
 */
@Service
public class AppointMentServiceImpl implements AppointMentService {
    @Autowired
    private AppointMentDao appointMentDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private AppointMentLogDao appointMentLogDao;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private MachineBorrowDao machineBorrowDao;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private TerOnlineDao terOnlineDao;
    @Autowired
    private AccountConfigDao accountConfigDao;
    @Autowired
    private GeoService geoService;
    @Autowired
    private TerControlService terControlService;
    @Autowired
    private UserService userService;
    @Autowired
    private UserBlackListService userBlackListService;
    @Autowired
    private MachineFaultService machineFaultService;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;

    @Override
    public List<AppointMentLog> queryPage(Integer userId, Integer pageNO, Integer rowCount) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("page", (pageNO - 1) * rowCount);
        map.put("rowCount", rowCount);
        return appointMentLogDao.queryPage(map);
    }

    @Override
    public Integer queryCount(Integer userId) {
        return appointMentLogDao.queryCount(userId);
    }

    @Override
    public AppointMent getByUserId(Integer userId) {
        AppointMent appointMent = appointMentDao.getByUserId(userId);
        if (appointMent == null) {
            return null;
        }
        AccountConfig accountConfig = cacheService.getConfig(appointMent.getAccountId());
        if (appointMent != null) {
            /**判断预约是否达到预约时长*/
            if (DateTimeUtil.getTimeDF(DateTimeUtil.getLastTime(DateTimeUtil.DateTimeToString(appointMent.getAppointmentTime()), accountConfig.getAppointTime() * 60),
                    DateTimeUtil.getNowTime()) >= 0) {
                appointMentDao.del(appointMent.getUserId());
                appointMent = null;
            } else {
                Machine machine = machineDao.getByMachineId(appointMent.getMachineId());
                MachineStatus machineStatus = machineStatusService.getByMachineNO(machine.getMachineNO(), 2);
                appointMent.setMachineNO(machine.getMachineNO());
                if (machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null) {
                    appointMent.setSocPercent(machineStatus.getSocPercent());
                    appointMent.setSurplusMileage(machineStatus.getSurplusMileage());
                }
            }
        }
        return appointMent;
    }

    @Override
    public void add(AppointMent appointMent) {
        Machine machine = machineDao.getByUserCode(appointMent.getUserCode());
        if (machine == null) {
            throw new BaseException("-30005", "设备不存在");
        }
        if (machine.getState().equals(MachineStateConstant.MACHINE_STATE_DTF)) {
            throw new BaseException("-3029", "故障车辆，车辆还没有投放");
        }
        if (machine.getState().equals(MachineStateConstant.MACHINE_STATE_DDD)) {
            throw new BaseException("-3029", "故障车辆，车辆还没有投放");
        }

        if (machine.getState().equals(MachineStateConstant.MACHINE_STATE_GZ)) {
            throw new BaseException("-3028", "故障车辆，请更换一辆");
        }

        if (machine.getState().equals(MachineStateConstant.MACHINE_STATE_BF)) {
            throw new BaseException("-3028", "报废车辆，请更换一辆");
        }

    /*Online online = terOnlineDao.getByMachineNO(machine.getMachineNO());
    if(online==null||online.getOnline()==0){
      throw new BaseException("-3028","故障车辆，请更换一辆车");
    }*/
        AccountConfig accountConfig = cacheService.getConfig(machine.getAccountId());
        MachineStatus machineStatus = machineStatusService.getByMachineNO(machine.getMachineNO(), MapConstant.MAP_BAIDU);
        if (machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null && machineStatus.getBatDt() != null
                && DateTimeUtil.getTimeDF(machineStatus.getBatDt(), DateTimeUtil.getNowTime()) <= 300) {
            if (machineStatus.getLon() == null || machineStatus.getLat() == null) {
                throw new BaseException("-3029", "故障车辆，车辆还没有上线");
            }
            Boolean isInArea = geoService.checkInGeo(machine.getAccountId(), new Point(machineStatus.getLon(), machineStatus.getLat()));
            if (!isInArea) {
                throw new BaseException("-3047", "运营区域外禁止借车");
            }
            /**电量是否足够*/
            if (machineStatus.getSocPercent() <= accountConfig.getBorrowSocLimit()) {
                /**发送电量不足语音指令*/
                String serNO = UUID.randomUUID().toString();
                terControlService.sendControl(serNO, machine.getMachineNO(), ControlTypeConstant.CONTROL_TYPE_VOICE,
                        ControlTypeConstant.CONTROL_TYPE_VOICE_LOWPOWER, "", machine, true, 1, 1, null);
                throw new BaseException("-3031", "电量过低，请更换一辆车");
            }
            /**兼容用户上报故障车辆是否可预约*/
            if ((accountConfig != null && accountConfig.getUserFaultLimit() == 1)) {
                MachineFault machineFault = machineFaultService.getByMachineId(machine.getMachineId());
                if (machineFault != null && machineFault.getFrom() == 1) {
                    throw new BaseException("-3028", "故障车辆，请更换一辆");
                }
            }
            if (this.userFeedbackLimit(machine.getAccountId())) {
                MachineFault machineFault = machineFaultService.getByMachineId(machine.getMachineId());
                if (machineFault != null && machineFault.getFrom() == 3) {
                    throw new BaseException("-3028", "故障车辆，请更换一辆");
                }
            }
        } else {
            throw new BaseException("-3029", "故障车辆，车辆还没有投放");
        }
        User user = userService.getByUserId(appointMent.getUserId());
        /**判断是否在黑名单*/
        UserBlackList userBlackList = userBlackListService.getByUserId(appointMent.getUserId());
        if (userBlackList != null &&
                DateTimeUtil.getTimeDF(DateTimeUtil.getNowTime(), userBlackList.getExpireTime() + " 00:00:00") > 0) {
            throw new BaseException("-3036", "被加入黑名单，功能被限制");
        }

        List<UserBlackList> userBlackLists = userBlackListService.getByIdNO(user.getIdNO());
        if (userBlackLists.size() > 0) {
            for (UserBlackList userBlackListDB : userBlackLists) {
                if (userBlackListDB != null &&
                        DateTimeUtil.getTimeDF(DateTimeUtil.getNowTime(), userBlackListDB.getExpireTime() + " 00:00:00") > 0) {
                    throw new BaseException("-3036", "被加入黑名单，功能被限制");
                }
            }
        }
        appointMent.setMachineId(machine.getMachineId());
        appointMent.setAccountId(machine.getAccountId());
        /**车辆是否正在骑行*/
        MachineBorrow machineBorrow = machineBorrowDao.getByMachineId(appointMent.getMachineId());
        if (machineBorrow != null) {
            throw new BaseException("-3001", "该车正在骑行");
        }

        if (accountConfig == null) {
            throw new BaseException("-160002", "该功能未配置");
        }
        if (accountConfig.getAppoint() == 0) {
            throw new BaseException("-160002", "该功能未配置");
        }
        Integer count = appointMentLogDao.getTodayAppoint(appointMent.getUserId());
        /**是否超出每天预约次数*/
        if (count >= accountConfig.getAppointDayTimes()) {
            throw new BaseException("-160003", "超出每天预约上限");
        }
        AppointMent appointMentDB = getByUserId(appointMent.getUserId());
        if (appointMentDB != null) {
            throw new BaseException("-160001", "已存在预约车辆，请勿重复预约");
        }
        AppointMent appointMent1 = appointMentDao.getByMachineId(machine.getMachineId());
        if (appointMent1 != null) {
            throw new BaseException("-160004", "该车辆已被预约，请换一台车");
        }
        appointMent.setAppointmentTime(new Date());
        appointMentDao.add(appointMent);
        AppointMentLog appointMentLog = new AppointMentLog();
        appointMentLog.setAccountId(appointMent.getAccountId());
        appointMentLog.setAppointmentTime(new Date());
        appointMentLog.setMachineId(machine.getMachineId());
        appointMentLog.setMachineNO(machine.getMachineNO());
        appointMentLog.setUserCode(machine.getUserCode());
        appointMentLog.setUserId(appointMent.getUserId());
        appointMentLogDao.add(appointMentLog);
    }

    @Override
    public void del(Integer userId) {
        appointMentDao.del(userId);
    }

    /**
     * @description: 根据平台id判断是否开启了意见反馈的借车限制开关
     * @author: mo.shanyong
     * @date: 2024/11/20 10:25
     * @param: accountId 所在的平台id
     * @return: boolean
     */
    public boolean userFeedbackLimit(Integer accountId){
        AccountConfigExt configExt = accountConfigExtDao.selectByAccountIdAndKey(accountId, AccountConfigExtConstant.USER_FEEDBACK_LIMIT);
        return Objects.nonNull(configExt) && Integer.valueOf(configExt.getParamValue()) == 1;
    }
}
